package listener

import (
	"encoding/json"
	"fmt"
	"github.com/sirupsen/logrus"
	"hcy-api/lib/id"
	"hcy-api/structs/constant"
	"hcy-api/structs/idp"
	"idp/global"
	"net"
)

// tcp监听到的消息的统一入口

func (s *TcpServer) HandMsg(m idp.ClientResponse, conn net.Conn) {
	// 通过 ClientType 处理不同系统的客户端， 通过 Timely 对离线数据和实时数据分别处理。现在还用不到，预留的字段
	switch m.Code {
	case constant.Heartbeat:
		s.handlePing(m)
	case constant.WhoAmiForIdp:
		s.HandleViHandsUp(m, conn)
	case constant.GuarderPipMsg:
		IdpHandler.HandleGuarderPipMsg(m)
	case constant.ExecutePlugin:
		key := fmt.Sprintf("result_%d_%s_%v", m.DeviceId, m.Content.Plugin, m.Content.Args)
		if val, ok := global.InstructResultMap.Load(key); ok {
			if val == "" {
				global.InstructResultMap.Store(key, m.Content.Result)
			}
		}
		switch m.ClientType {
		case "vi-client":
			IdpHandler.HandleCliMsg(m)
		case "va-host":
		default:
			logrus.Error("undefined client type")
		}
	default:
		logrus.Debug("undefined messages:", m)
	}

}

func (s *TcpServer) handlePing(m idp.ClientResponse) {
	var (
		p idp.PingPcLoad
	)
	if err := json.Unmarshal([]byte(m.Content.Result), &p); err != nil {
		logrus.Error(err)
		return
	}
	if v, ok := global.InfoCatchMaoForIdp.Load(m.DeviceId); ok {
		obj := v.(*global.IdpCache)
		obj.CpuPer = p.CPU
		obj.MemoryPer = p.Memory
	}
}

// HandleViHandsUp 处理miao模块客户端的举手信息
func (s *TcpServer) HandleViHandsUp(m idp.ClientResponse, conn net.Conn) {
	var (
		bi       idp.HandsUpMsgForVi
		clientId int64
		err      error
		isNew    bool
	)
	err = json.Unmarshal([]byte(m.Content.Result), &bi)
	if err != nil {
		logrus.Errorf("不合法的 HandsUp 消息：%v", m)
		return
	}
	if clientId, isNew, err = IdpHandler.GetDeviceId(idp.HandsUpMsgForVi{
		Md5:             bi.Md5,
		BiosSerial:      bi.BiosSerial,
		MainBoardSerial: bi.MainBoardSerial,
		HardDiskSerial:  bi.HardDiskSerial,
		ActiveMAC:       bi.ActiveMAC,
		IP:              bi.IP,
		Hostname:        bi.Hostname,
	}); err != nil {
		logrus.Error(err)
		return
	}
	if clientId > 0 {
		s.clientOnline(clientId, conn)
		global.InfoCatchMaoForIdp.Store(clientId, &global.IdpCache{HandsUpMsg: bi})
		err = sendInstructForSetDeviceId(clientId, conn)
		if err != nil {
			logrus.Error("通知客户端设置ID失败,err:", err)
		}
		if isNew {
			Full(clientId)
		}
		// 开启一个协程去准备客户端的各种缓存任务
		go PrepareInstruct(clientId)
	} else {
		clientId = id.GetSnowId()
		s.clientOnline(clientId, conn)
		global.AbnormalDeviceForIdp.Store(clientId, &global.AbnormalDevice{
			HandsUpMsg: bi,
			Conn:       conn,
		})
	}
	s.StartGuarder(clientId)
}

// StartGuarder  启动守卫进程
func (s *TcpServer) StartGuarder(clientId int64) {
	err := SendInstruct(clientId, constant.StartGuarder, "guarder.exe", []string{"-c=90", "-m=0.9"})
	if err != nil {
		logrus.Error(err)
	}
}
